package com.dingup.provider.service.sys.impl;

import com.dingup.api.model.sys.SysPermission;
import com.dingup.api.model.sys.SysPermissionGroup;
import com.dingup.api.model.sys.SysPermissionGroupRole;
import com.dingup.api.model.sys.SysRole;
import com.dingup.provider.mapper.SysPermissionGroupMapper;
import com.dingup.provider.mapper.SysPermissionGroupRoleMapper;
import com.dingup.provider.mapper.SysPermissionMapper;
import com.dingup.provider.model.sys.UpdateRolePermission;
import com.dingup.provider.service.sys.SysPermissionService;
import com.dingup.provider.service.sys.SysRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by wancheng on 2018/7/28.
 */
@Service
public class SysPermissionServiceImpl implements SysPermissionService {

    @Autowired
    SysPermissionGroupMapper sysPermissionGroupMapper;
    @Autowired
    SysPermissionGroupRoleMapper sysPermissionGroupRoleMapper;
    @Autowired
    SysPermissionMapper sysPermissionMapper;
    @Autowired
    SysRoleService sysRoleService;

    @Override
    public List<SysPermissionGroup> getAll() {
        return sysPermissionGroupMapper.getAll();
    }

    @Override
    public List<SysPermissionGroup> getRolePermissionGroupByRoleId(Integer roleId) {

        return sysPermissionGroupMapper.getUserPermissionGroupByRoleId(roleId);
    }

    @Override
    public List<SysPermissionGroup> getRolePermissionGroupByUserId(String userId) {
        return sysPermissionGroupMapper.getUserPermissionGroupByUserId(userId);
    }

    @Override
    public List<SysPermission> getRolePermissionByUserId(String userId) {
        return null;
    }

    @Override
    public List<SysPermissionGroup> getRoleHasPermissionGroupTreeByRoleId(Integer roleId) {

        List<SysPermissionGroup> all = getAll();

        List<SysPermissionGroup> rolePermission = getRolePermissionGroupByRoleId(roleId);

        return union(all, rolePermission);
    }

    @Override
    public List<SysPermissionGroup> getRoleHasPermissionGroupTreeByRoleIdAndUserId(Integer roleId, String userId) {

        SysRole role = sysRoleService.getById(roleId);

        Boolean ifSysRole = false;

        if (role.getCreateUserId() == null) {
            ifSysRole = true;
        }

        List<SysPermissionGroup> all = getAll();

        List<SysPermissionGroup> rolePermission = getRolePermissionGroupByRoleId(roleId);

        List<SysPermissionGroup> userPermission = getRolePermissionGroupByUserId(userId);

        return union(all, userPermission, rolePermission, ifSysRole);
    }

    @Override
    public Map<String, Boolean> getRoleHasPermissionGroupTreeByUserId(String userId) {
        List<SysPermissionGroup> all = getAll();

        List<SysPermissionGroup> userPermission = getRolePermissionGroupByUserId(userId);

        Map<Integer, SysPermissionGroup> allMap = all.stream().collect(Collectors.toMap(SysPermissionGroup::getId, SysPermissionGroup -> SysPermissionGroup));

        userPermission.stream().distinct().forEach(
                sysPermissionGroup -> {
                    allMap.get(sysPermissionGroup.getId()).setIfHasPermission(true);
                    if (sysPermissionGroup.getParentId() != 0) {
                        allMap.get(sysPermissionGroup.getParentId()).setIfHasPermission(true);
                    }
                }
        );
        all = allMap.entrySet().stream().map(en -> en.getValue()).collect(Collectors.toList());
        Map<String, Boolean> res = all.stream().collect(Collectors.toMap(SysPermissionGroup::getGroupPermission, SysPermissionGroup -> SysPermissionGroup.getIfHasPermission()));
        return res;
    }

    @Override
    public Boolean deleteRolePermission(Integer roleId) {
        sysPermissionGroupRoleMapper.deleteByRoleId(roleId);
        return true;
    }

    @Override
    @Transactional
    public Boolean updateRolePermission(Integer roleId, List<UpdateRolePermission> list) {
        list.stream().forEach(
                updateRolePermission -> {
                    if (updateRolePermission.getIfHasPermission()) {
                        SysPermissionGroupRole sysPermissionGroupRole = sysPermissionGroupRoleMapper.selectByRoleIdAndGroupId(roleId, updateRolePermission.getId());
                        if (sysPermissionGroupRole == null) {
                            sysPermissionGroupRole = new SysPermissionGroupRole();
                            sysPermissionGroupRole.setCreateTime(new Date());
                            sysPermissionGroupRole.setSysRoleId(roleId);
                            sysPermissionGroupRole.setStatus(true);
                            sysPermissionGroupRole.setSysPermissionGroupId(updateRolePermission.getId());
                            sysPermissionGroupRoleMapper.insertSelective(sysPermissionGroupRole);
                        } else {
                            sysPermissionGroupRole.setCreateTime(new Date());
                            sysPermissionGroupRole.setSysRoleId(roleId);
                            sysPermissionGroupRole.setStatus(true);
                            sysPermissionGroupRole.setSysPermissionGroupId(updateRolePermission.getId());
                            sysPermissionGroupRoleMapper.updateByPrimaryKeySelective(sysPermissionGroupRole);
                        }
                    } else {
                        SysPermissionGroupRole sysPermissionGroupRole = sysPermissionGroupRoleMapper.selectByRoleIdAndGroupId(roleId, updateRolePermission.getId());
                        if (sysPermissionGroupRole != null) {
                            sysPermissionGroupRoleMapper.deleteByPrimaryKey(sysPermissionGroupRole.getId());
                        }
                    }
                }
        );
        return null;
    }

    @Override
    public List<SysPermission> getAllPermission() {
        return sysPermissionMapper.getAll();
    }

    @Override
    public List<String> getPermissionByUserId(String userId) {
        Map<String,Boolean> permission = getRoleHasPermissionGroupTreeByUserId(userId);
        List<String> res = new ArrayList<>();
        permission.entrySet().stream().forEach(
                p->{
                    if(p.getValue()){
                        res.add(p.getKey());
                    }
                }
        );
        return res;
    }

    private List<SysPermissionGroup> union(List<SysPermissionGroup> all, List<SysPermissionGroup> userPermission) {
        Map<Integer, SysPermissionGroup> allMap = all.stream().collect(Collectors.toMap(SysPermissionGroup::getId, SysPermissionGroup -> SysPermissionGroup));
        userPermission.stream().distinct().forEach(
                sysPermissionGroup -> {
                    allMap.get(sysPermissionGroup.getId()).setIfHasPermission(true);
                }
        );
        all = allMap.entrySet().stream().map(en -> en.getValue()).collect(Collectors.toList());
        Map<Integer, List<SysPermissionGroup>> res = all.stream().collect(Collectors.groupingBy(SysPermissionGroup::getParentId));
        List<SysPermissionGroup> parent = res.get(0);
        parent.stream().forEach(
                group -> {
                    group.setChild(res.get(group.getId()));
                }
        );
        return parent;
    }

    private List<SysPermissionGroup> union(List<SysPermissionGroup> all, List<SysPermissionGroup> userPermission, List<SysPermissionGroup> rolePermission, Boolean ifSysRole) {

        //这里 status表示权限的禁止编辑状态  初始化所有权限的编辑状态
        all.parallelStream().forEach(
                sysPermissionGroup -> {
                    sysPermissionGroup.setStatus(false);
                }
        );
        Map<Integer, SysPermissionGroup> allMap = all.stream().collect(Collectors.toMap(SysPermissionGroup::getId, SysPermissionGroup -> SysPermissionGroup));
        rolePermission.stream().distinct().forEach(
                sysPermissionGroup -> {
                    allMap.get(sysPermissionGroup.getId()).setIfHasPermission(true);
                }
        );
        if (!ifSysRole) {
            userPermission.stream().distinct().forEach(
                    sysPermissionGroup -> {
                        allMap.get(sysPermissionGroup.getId()).setStatus(true);
                    }
            );
        }
        all = allMap.entrySet().stream().map(en -> en.getValue()).collect(Collectors.toList());
        Map<Integer, List<SysPermissionGroup>> res = all.stream().collect(Collectors.groupingBy(SysPermissionGroup::getParentId));
        List<SysPermissionGroup> parent = res.get(0);
        parent.stream().forEach(
                group -> {
                    group.setChild(res.get(group.getId()));
                }
        );
        parent.parallelStream().forEach(
                p -> {
                    p.getChild().sort(((o1, o2) -> o1.getOrder().compareTo(o2.getOrder())));
                }
        );
        return parent;
    }
}
